﻿/// <summary>
/// Developer: CHOOI KAH WAI
/// Last Modified: 24/10/2009
/// </summary>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ARSS.Common;
using System.Windows.Media.Media3D;
using System.Collections;
using System.Xml.Linq;
using System.Windows.Media.Animation;
using System.Windows;

namespace ARSS.Visual
{
    /// <summary>
    /// Scene node class
    /// </summary>
    public class SceneNode
    {
        #region Properties

        /// <summary>
        /// 3D model file path
        /// </summary>
        public string ModelPath { get; set; }

        /// <summary>
        /// Marker ID representing this scene node
        /// </summary>
        public int MarkerID { get; set; }

        /// <summary>
        /// Node's children
        /// </summary>
        public ArrayList Children { get; set; }

        /// <summary>
        /// Scale value
        /// </summary>
        public Vector3D Scale { get; set; }

        /// <summary>
        /// Rotation value
        /// </summary>
        public Vector3D Rotation { get; set; }

        /// <summary>
        /// Translation value
        /// </summary>
        public Vector3D Translation { get; set; }

        /// <summary>
        /// Local transformation matrix
        /// </summary>
        public Matrix3D TransformMatrix { get; set; }

        /// <summary>
        /// Scene node name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Scene node 3D model
        /// </summary>
        public ModelVisual3D Model3D { get; set; }

        /// <summary>
        /// Parent scene node
        /// </summary>
        public SceneNode ParentNode { get; set; }

        /// <summary>
        /// This node is currently locked by who?
        /// </summary>
        public string Locker { get; set; }

        #endregion

        #region Functions

        /// <summary>
        /// Constructor
        /// </summary>
        public SceneNode()
        {
            ModelPath = "";
            Name = "";
            Locker = "";
            MarkerID = -1;
            Children = new ArrayList();
            TransformMatrix = Matrix3D.Identity;
            Model3D = null;
            ParentNode = null;
        }

        /// <summary>
        /// Load Scene Node
        /// </summary>
        /// <param name="nodeElement">Scene Node data</param>
        public void LoadNode(XElement nodeElement)
        {
            ModelPath = nodeElement.Attribute("model").Value;
            Name = nodeElement.Attribute("name").Value;

            // Load transformation
            Transform3DGroup tg = new Transform3DGroup();

            // Rotation
            Vector3D vec = new Vector3D(double.Parse(nodeElement.Element("Rotate").Attribute("x").Value),
                                double.Parse(nodeElement.Element("Rotate").Attribute("y").Value),
                                 double.Parse(nodeElement.Element("Rotate").Attribute("z").Value));

            tg.Children.Add(new RotateTransform3D(
                                                    new AxisAngleRotation3D(new Vector3D(1, 0, 0), vec.X)));
            tg.Children.Add(new RotateTransform3D(
                                                    new AxisAngleRotation3D(new Vector3D(0, 1, 0), vec.Y)));
            tg.Children.Add(new RotateTransform3D(
                                                    new AxisAngleRotation3D(new Vector3D(0, 0, 1), vec.Z)));
            Rotation = vec;

            // Scale
            vec = new Vector3D(double.Parse(nodeElement.Element("Scale").Attribute("x").Value),
                                double.Parse(nodeElement.Element("Scale").Attribute("y").Value),
                                 double.Parse(nodeElement.Element("Scale").Attribute("z").Value));
            tg.Children.Add(new ScaleTransform3D(vec));
            Scale = vec;

            // Translation
            vec = new Vector3D(double.Parse(nodeElement.Element("Translate").Attribute("x").Value),
                                double.Parse(nodeElement.Element("Translate").Attribute("y").Value),
                                 double.Parse(nodeElement.Element("Translate").Attribute("z").Value));
            tg.Children.Add(new TranslateTransform3D(vec));
            Translation = vec;

            TransformMatrix = tg.Value;


            // Load children
            if (nodeElement.Element("Children") != null)
            {
                foreach (XElement ele in nodeElement.Element("Children").Elements("Child"))
                {
                    SceneNode child = new SceneNode();
                    child.LoadNode(ele);
                    child.ParentNode = this;
                    Children.Add(child);
                }
            }
        }

        #endregion
    }
}
